<?php
/**
 * Created by PhpStorm.
 * User: admin
 * Date: 2018/7/23
 * Time: 10:45
 */

namespace app\common\biz;

use app\common\exception\BizException;
use think\Exception;
use think\facade\Log;

class BaseBiz
{
    //登录信息
    public static $_account;
    //内部数据
    protected $data;
    //验证结果
    public static $_check;
    //验证失败时的结果
    public static $_code;
    //验证失败时的信息
    public static $_message = '';
    //是否安全返回结果
    protected $safety = false;
    //单例模式
    protected static $_instance;

    /**
     * BaseLogic constructor.
     * @param array $data
     * @throws \Exception
     */
    function __construct(array $data=[])
    {
        if(self::$_check===false)
            throw new BizException(self::$_message,self::$_code);

        $this->data = $data;
    }

    /**
     * instance
     * @param array $data
     * @return mixed
     * @throws \Exception
     */
    final public static function instance(array $data=[])
    {
        if (is_null(static::$_instance))
            static::$_instance = new static($data);

        return static::$_instance;
    }

    /**
     * set inside parameters
     * @param array $data
     */
    public function setData(array $data)
    {
        $this->data = $data;
    }

    /**
     * set verify status when conditions are met
     * @param bool $status
     */
    public static function setStatus(bool $status)
    {
        if(false!==self::$_check)
            self::$_check = $status;
    }

    /**
     * set reason info with verify failed,and only record the first one.
     * @param int $code
     */
    public static function setFailedCode(int $code)
    {
        if(is_null(self::$_code))
            self::$_code = $code;
    }

    /**
     * set reason info with verify failed,and only record the first one.
     * @param string|array $message
     */
    public static function setFailedMessage(string $message)
    {
        if(is_null(self::$_message))
            self::$_message = $message;
    }

    /**
     * safe return null if call function throw LogicException
     * @return $this
     */
    public function safe()
    {
        $this->safety = true;
        return $this;
    }

    /**
     * business logic throw exception handling
     * 该异常会预期的返回至请求响应
     * @param $msg
     * @param int $bizCode
     * @throws BizException
     */
    protected static function exception($msg, $bizCode=FAILED)
    {
        throw new BizException($msg, $bizCode);
    }

    /**
     * magic function
     * @param $name
     * @param $arguments
     * @return null
     * @throws \Exception
     */
    public function __call($name, $arguments)
    {
        if(self::$_check===false) {
            throw new BizException(self::$_message,self::$_code ?: NOT_CHECK);
        }

        if(!method_exists($this,$name))
            throw new Exception('Not Found Method '.get_class($this)."->$name()");
        // TODO: Implement __call() method.
        /**
         * 下面这一段代码的处理逻辑的目的是为了不同同事之间能够友好的协同操作，具体容我细细道来
         * 一般具体到逻辑的实现方法中，该方法预期的结果应该是返回值和异常
         * 当你调用别人的逻辑类的时候，如果该方法正常执行还好，如果不正常执行，即报错的时候
         * 如果你没有做容错处理，那么你的逻辑方法就会直接抛出异常，从而影响你后续的整段逻辑，即使有的时候你的本意仅仅只是尝试的去调用一下
         * 所以你在调用别人逻辑方法的时候，如果是业务非阻塞调用，那么你都通通需要做容错处理
         * 所以本着为同事服务的宗旨，我就添加了一个safe方法，链式调用的时候 ex：$xxxLogic->safe()->action()
         * 如果异常就安全返回null，并不会直接粗暴的抛出异常
         */
        try{
            $result = $this->$name(...$arguments);
        } catch (BizException $e) {
            if(!$this->safety) {
                throw new BizException($e->getMessage(),$e->getBizCode());
            }
            Log::record('[ 逻辑类调用异常 ] '.$e->getMessage(),'logic');
            $result = null;
            $this->safety = false;
        }

        return $result;
    }
}